package com.heima.wemedia.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.heima.common.constants.KafkaMessageConstant;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dto.WmNewsDto;
import com.heima.model.wemedia.dto.WmNewsPageReqDto;
import com.heima.model.wemedia.entity.WmMaterial;
import com.heima.model.wemedia.entity.WmNews;
import com.heima.wemedia.dao.WmMaterialDao;
import com.heima.wemedia.dao.WmNewsDao;
import com.heima.wemedia.dao.WmNewsMaterialDao;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.utils.WmThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 自媒体文章表(WmNews)表服务实现类
 *
 * @author makejava
 * @since 2022-04-13 17:22:34
 */
@Service("wmNewsService")
public class WmNewsServiceImpl implements WmNewsService {
    @Resource
    private WmNewsDao wmNewsDao;

    @Resource
    private WmNewsMaterialDao wmNewsMaterialDao;

    @Resource
    private WmMaterialDao wmMaterialDao;

    @Resource
    private KafkaTemplate kafkaTemplate;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public WmNews queryById(Long id) {
        return this.wmNewsDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param wmNews 筛选条件
     * @param pageRequest      分页对象
     * @return 查询结果
     */
    @Override
    public Page<WmNews> queryByPage(WmNews wmNews, PageRequest pageRequest) {
        long total = this.wmNewsDao.count(wmNews);
        return new PageImpl<>(this.wmNewsDao.queryAllByLimit(wmNews, pageRequest), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param wmNews 实例对象
     * @return 实例对象
     */
    @Override
    public WmNews insert(WmNews wmNews) {
        this.wmNewsDao.insert(wmNews);
        return wmNews;
    }

    /**
     * 修改数据
     *
     * @param wmNews 实例对象
     * @return 实例对象
     */
    @Override
    public WmNews update(WmNews wmNews) {
        this.wmNewsDao.update(wmNews);
        return this.queryById(wmNews.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public ResponseResult deleteById(Long id) {
        //1.根据id查询文章详情
        WmNews wmNews = wmNewsDao.queryById(id);
        if (wmNews==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2.判断文章状态
        if (wmNews.getStatus()==9) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH,"已发布文章不能删除");
        }
        //3.删除文章数据
        wmNewsDao.deleteById(id);
        //4.删除文章素材管理数据
        wmNewsMaterialDao.deleteByNewsId(wmNews.getId());

        return ResponseResult.okResult("删除文章成功");
    }

    /**
     * 保存文章数据
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //1.校验参数
        if (dto==null || StringUtils.isBlank(dto.getTitle())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2.处理数据，封装数据
        WmNews wmNews=new WmNews();
        //copy前提：属性名称和类型必须完全一样，不一样的字段是无法复制到
        BeanUtils.copyProperties(dto,wmNews);
        //labels  images  type 属性不一致
        wmNews.setLabels(dto.getLabels());

        //2.1抽取封面图片到内容图片
        List<String> cover_images = dto.getImages();
        List<String> content_images=extractContentImage(dto.getContent());

        //2.2文章布局类型处理
        if (dto.getType()==-1) {
            //2.2.1如果内容图片数量>=3，提取三张图片作为封面，封面类型：三图
            if (content_images.size()>=3) {
                 cover_images = content_images.stream().limit(3).collect(Collectors.toList());
                 wmNews.setType(3);
            }else if (content_images.size()>0&&content_images.size()<3){
                //2.2.2如果0<内容图片数量＜3 ，提取一张图片作为封面，封面类型：单图
                cover_images=content_images.stream().limit(1).collect(Collectors.toList());
                wmNews.setType(1);
            }else {
                cover_images= Collections.emptyList();
                wmNews.setType(0);
            }
            //2.2.3如果内容图片数量=0，封面类型：无图
        }

        wmNews.setImages(StringUtils.join(cover_images.toArray(),","));

        //3.保存文章信息到数据库
        saveWmNews(wmNews);
        //4.保存文章和素材关联信息(封面引用,内容引用)
        //4.1保存封面引用关联关系
        saveCoverMatarialRelation(wmNews.getId(),cover_images);
        //4.2保存内容引用关联关系
        saveContentMatarialRelation(wmNews.getId(),content_images);

        //发送消息通知审核服务进行文章审核
        kafkaTemplate.send(KafkaMessageConstant.NEWS_AUTO_SCAN_TOPIC,wmNews.getId()+"");

        //5.封装数据返回
        return ResponseResult.okResult("文章发布成功");
    }


    /**
     * 保存文章和素材的引用关系
     * @param newsId    文章Id
     * @param images    图片URL
     * @param type      引用类型 0：封面引用， 1:内容引用
     */
    private void saveMatarialRelation(Long newsId, List<String> images, int type) {
        //1. 参数校验
        if (CollectionUtils.isEmpty(images)) {
            return;
        }

        //2.保存文章和素材关系
        //2.1根据素材url获取素材Id      in(url1,url2,url3)
        images=images.stream().distinct().collect(Collectors.toList());
        List<WmMaterial> materialList= wmMaterialDao.queryByUrls(images);
        //2.2获取素材id
        List<Long> ids = materialList.stream().map(wmMaterial -> wmMaterial.getId()).collect(Collectors.toList());

        //2.3判断素材是否缺失
        if (images.size()!=ids.size()) {
            throw new RuntimeException("素材图片缺失");
        }

        //2.4保存文章和素材的管理关系
        //inster into wm_news_material () values (),(),()
        wmNewsMaterialDao.saveNewsRelation(newsId,ids,type);
    }


    /**
     * 保存文章和内容图片的引用关系
     * @param newsId
     * @param content_images
     */
    private void saveContentMatarialRelation(Long newsId, List<String> content_images) {
        saveMatarialRelation(newsId,content_images,1);
    }



    /**
     * 保存文章和封面图片的引用关系
     * @param newsId
     * @param cover_images
     */
    private void saveCoverMatarialRelation(Long newsId, List<String> cover_images) {
        saveMatarialRelation(newsId,cover_images,0);
    }

    /**
     * 保存文章信息到数据库
     * @param wmNews
     */
    private void saveWmNews(WmNews wmNews) {
        //1.补全数据
        wmNews.setUserId(WmThreadLocalUtil.get().getId());
        wmNews.setEnable(1);
        wmNews.setCreatedTime(new Date());
        wmNews.setUpdatedTime(new Date());

        //2.保存数据到数据库    保存|更新
        if (wmNews.getId()==null) {
            wmNewsDao.insert(wmNews);
            return;
        }

        wmNewsDao.update(wmNews);

        //如果是修改，需要删除文章和素材的引用关系
        wmNewsMaterialDao.deleteByNewsId(wmNews.getId());


    }

    public static void main(String[] args) {
        String[] strs={"a","b"};
        String join = StringUtils.join(strs, ",");
        System.out.println("join = " + join);
    }

    /**
     * 从文章内容中抽取图片数据
     * @param content
     * @return
     */
    private List<String> extractContentImage(String content) {
        //1.将文章内容转换为Java集合
        List<Map> list = JSON.parseArray(content, Map.class);
        //2.遍历获取每一部分数据
        List<String> imageList = list.stream()
                //过滤  ---type=image保留
                .filter(map -> map.get("type").equals("image"))
                //转换--->把流中的每一个map，转化为图片路劲字符串
                .map(map -> map.get("value").toString())
                .collect(Collectors.toList());

        return imageList;
    }

    @Override
    public ResponseResult list(WmNewsPageReqDto dto) {
        //参数校验
        dto.checkParam();
        //条件-----> 状态 ：精确  ，频道：精确，发布时间：范围查询 ，关键字：模糊查询， 用户id：精确
        //1.构造查询参数
        Map<String, Object> queryParam = BeanUtil.beanToMap(dto);
        queryParam.put("userId",WmThreadLocalUtil.get().getId());

        //2.开启分页查询
        PageHelper.startPage(dto.getPage(),dto.getSize());
        //3.执行查询
       com.github.pagehelper.Page<WmNews> page= wmNewsDao.queryByMap(queryParam);
       //4.封装数据返回
        ResponseResult result=new PageResponseResult(page.getPageNum(),page.getPageSize(), (int) page.getTotal());
        result.setData(page.getResult());
        return result;
    }
}
